package IPYUN

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"gitee.com/tools/internal/domain"
	"gitee.com/tools/internal/service/IP"
	"io"
	"log"
	"net/http"
	"strings"
	"sync"
	"time"
)

type IpYunService struct {
	key  string
	api  string
	lock sync.Mutex
}

func (i *IpYunService) QueryCountryCode(ctx context.Context, words string, t string) (domain.CountryCode, error) {
	//TODO implement me
	panic("implement me")
}

func (i *IpYunService) QueryPhone(ctx context.Context, mobile string, status bool) (domain.MPhone, error) {
	//TODO implement me
	panic("implement me")
}
func (i *IpYunService) QueryDns(ctx context.Context, data domain.Dns) (string, error) {
	//TODO implement me
	panic("implement me")
}
func (i *IpYunService) QueryIp(ctx context.Context, ip string) (domain.IpInfo, error) {
	ctx, cancel := context.WithTimeout(ctx, time.Second*1)
	defer cancel()
	i.lock.Lock()
	defer i.lock.Unlock()
	apiPath := fmt.Sprintf("%s?ip=%s&key=%s", i.api, ip, i.key)
	var info = domain.IpInfo{}
	resp, err := http.Get(apiPath)
	if err != nil {
		return info, err
	}
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return info, err
	}
	defer resp.Body.Close()
	if resp.StatusCode > 299 {
		err = fmt.Errorf("Response failed with status code: %d and\nbody: %s\n", resp.StatusCode, body)
		log.Println(err)
		return info, err
	}

	bodystr := string(body)
	if !strings.Contains(bodystr, "200") {
		log.Println("IP错误或者其他原因")
		return info, errors.New("IP错误或者其他原因")
	}

	//对返回的json数据做解析
	var datajson map[string]interface{}

	err = json.Unmarshal([]byte(bodystr), &datajson)
	modeljson := datajson["data"].(map[string]interface{})
	locationbyte, err := json.Marshal(modeljson["location"])
	if err != nil {
		return info, err
	}
	ifo := domain.IpInfos{}
	err = json.Unmarshal(locationbyte, &ifo)
	info = i.ToIpInfo(ifo)
	return info, err

}
func (i *IpYunService) QueryIpv1(ctx context.Context, ip string) (domain.IpInfos, error) {
	ctx, cancel := context.WithTimeout(ctx, time.Second*1)
	defer cancel()
	ch := make(chan error)
	defer close(ch)
	apiPath := fmt.Sprintf("%s?ip=%s&key=%s", i.api, ip, i.key)
	var info = domain.IpInfos{}
	var err error
	go func() {
		resp, err := http.Get(apiPath)
		if err != nil {
			ch <- err
			return
		}
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			ch <- err
			return
		}
		defer resp.Body.Close()
		if resp.StatusCode > 299 {
			err = fmt.Errorf("Response failed with status code: %d and\nbody: %s\n", resp.StatusCode, body)
			log.Println(err)
			ch <- err
			return
		}

		bodystr := string(body)
		if !strings.Contains(bodystr, "200") {
			log.Println("IP错误或者其他原因")
			ch <- errors.New("IP错误或者其他原因")
			return
		}

		//对返回的json数据做解析
		var datajson map[string]interface{}

		err = json.Unmarshal([]byte(bodystr), &datajson)
		modeljson := datajson["data"].(map[string]interface{})
		locationbyte, err := json.Marshal(modeljson["location"])

		err = json.Unmarshal(locationbyte, &info)
		if err != nil {
			ch <- err
			return
		}
	}()

	select {
	case <-ctx.Done():
		err = errors.New("查询超时")
	case er := <-ch:
		err = er
	}
	return info, err
}
func (i *IpYunService) ToIpInfo(infos domain.IpInfos) domain.IpInfo {
	return domain.IpInfo{
		AreaCode:       infos.AreaCode,
		City:           infos.City,
		CityCode:       infos.CityCode,
		Continent:      infos.Continent,
		Country:        infos.Country,
		CountryCode:    infos.CountryCode,
		District:       infos.District,
		Elevation:      infos.Elevation,
		Ip:             infos.Ip,
		Isp:            infos.Isp,
		Latitude:       infos.Latitude,
		Longitude:      infos.Longitude,
		MultiStreet:    infos.MultiStreet,
		Province:       infos.Province,
		Street:         infos.Street,
		TimeZone:       infos.TimeZone,
		WeatherStation: infos.WeatherStation,
		ZipCode:        infos.ZipCode,
	}
}
func NewIPYunSvc(key string) IP.Ip {
	return &IpYunService{
		key: key,
		api: "https://api.ipdatacloud.com/v2/query",
	}
}
